package com.spzx.product.receiver;

import com.rabbitmq.client.Channel;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.common.rabbit.constant.MqConst;
import com.spzx.product.service.ISkuStockService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.intellij.lang.annotations.MagicConstant;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author: atguigu
 * @create: 2025-02-28 11:55
 */
@Slf4j
@Component
public class ProductReceiver {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ISkuStockService skuStockService;

    /**
     * 解锁库存
     *
     * @param orderNo
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(MqConst.EXCHANGE_PRODUCT),
            value = @Queue(MqConst.QUEUE_UNLOCK),
            key = MqConst.ROUTING_UNLOCK
    ))
    public void unlockStock(String orderNo, Message message, Channel channel) {
        if (StringUtils.isNotEmpty(orderNo)) {
            log.info("订单服务接收到解锁库存消息，订单号：{}", orderNo);
            //1.进行幂等性处理 避免短暂时间内RabbitMQ由于网络抖动同一消息多次投递给消费者
            String redisKey = "sku:unlock:" + orderNo;
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(redisKey, orderNo, 5, TimeUnit.MINUTES);

            //2.解锁库存
            if (flag) {
                try {
                    skuStockService.unlockStock(orderNo);
                } catch (Exception e) {
                    log.error("订单服务解锁库存失败，订单号：{}", orderNo);
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
                }
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
    }


    /**
     * 用户支付成功后，扣减库存
     *
     * @param orderNo 订单编号
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(MqConst.EXCHANGE_PRODUCT),
            value = @Queue(MqConst.QUEUE_MINUS),
            key = MqConst.ROUTING_MINUS
    ))
    public void paySuccessMinusStock(String orderNo, Message message, Channel channel) {
        if (StringUtils.isNotEmpty(orderNo)) {
            log.info("商品服务接收到扣减库存消息，订单编号：{}", orderNo);
            //1.幂等性处理
            String key = "sku:minus:" + orderNo;
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, orderNo, 5, TimeUnit.MINUTES);
            if (flag) {
                try {
                    //2.扣减库存 异常：删除幂等性key
                    skuStockService.minusStock(orderNo);
                } catch (Exception e) {
                    redisTemplate.delete(key);
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
                }
            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
